iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
自我挑戰組

30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記系列 第 20

跨境支付換匯小工具:一眼看懂匯率、價差與手續費

  • 分享至 

  • xImage
  •  

我們要解決什麼?

當你用 TWD 付給海外商家(USD/EUR…)時,實際入帳金額會受到三件事影響:

  1. 中間價(mid):市場上 1 USD 可以換多少 TWD(或其他幣別)的「理論匯率」。
  2. 匯率價差(margin):金流或銀行報給你的匯率會比中間價差一點點,這就是它們的利潤來源。
  3. 手續費:固定費(例如 NT$30)+百分比費(例如 0.6%)。

今天的程式不連網,所以用「示意匯率」。你可以把數字換成你想測試的值。

Python 小實作

# 說明:
# - MID 為示意用「中間價」:1 USD 可換多少其它幣(非即時、非建議價)
# - PCT_FEE 百分比手續費(以來源幣計)
# - FLAT_FEE 固定手續費(以來源幣計)
# - FX_MARGIN 匯率價差(以中間價基礎打折,讓使用者拿到稍不利的匯率)

MID = {       # 1 USD = X 目標幣(示意數字,請依需求自行調整)
    "USD": 1.00,
    "TWD": 32.00,
    "EUR": 0.90,
    "JPY": 155.00,
}

CURRENCY_SYMBOL = {"USD": "$", "TWD": "NT$", "EUR": "€", "JPY": "¥"}

PCT_FEE   = 0.006   # 0.6% 百分比手續費(示意)
FLAT_FEE  = {       # 固定手續費(以來源幣別計,示意)
    "TWD": 30,
    "USD": 1.5,
    "EUR": 1.5,
    "JPY": 200,
}
FX_MARGIN = 0.008   # 匯率價差 0.8%(示意)

def fx_rate(src: str, dst: str) -> float:
    """用中間價計算 src→dst 的理論匯率(dst_per_src)"""
    return MID[dst] / MID[src]

def money(cur: str, val: float) -> str:
    sym = CURRENCY_SYMBOL.get(cur, "")
    if cur in ("TWD", "JPY"):
        return f"{sym}{val:,.0f}"
    return f"{sym}{val:,.2f}"

def quote(amount_src: float, src: str, dst: str,
          pct_fee=PCT_FEE, flat_fee_map=FLAT_FEE, fx_margin=FX_MARGIN):
    amt = float(amount_src)

    # 1) 手續費(以來源幣計)
    pct_fee_amt  = amt * pct_fee
    flat_fee_amt = float(flat_fee_map.get(src, 0.0))
    fees_src     = pct_fee_amt + flat_fee_amt
    net_src      = max(0.0, amt - fees_src)

    # 2) 匯率(中間價 → 扣價差)
    base_rate = fx_rate(src, dst)                 # 中間價
    eff_rate  = base_rate * (1 - fx_margin)       # 實際成交匯率(對使用者不利一點點)

    # 3) 換匯結果
    ideal_dst      = amt * base_rate              # 理想情況(無任何成本)
    margin_loss_dst= ideal_dst * fx_margin        # 價差造成的損耗(以目標幣表示)
    receive_dst    = net_src * eff_rate           # 扣完費用且套用價差後,實際可得

    return {
        "from": src, "to": dst,
        "amount_src": amt,
        "pct_fee_src": pct_fee_amt,
        "flat_fee_src": flat_fee_amt,
        "fees_src_total": fees_src,
        "net_src_after_fees": net_src,
        "mid_rate_src_to_dst": base_rate,
        "eff_rate_after_margin": eff_rate,
        "fx_margin": fx_margin,
        "ideal_dst_no_cost": ideal_dst,
        "fx_margin_loss_dst": margin_loss_dst,
        "receive_dst": receive_dst,
    }

def print_receipt(q: dict):
    print(f"=== 換匯報價 | {q['from']} → {q['to']} ===")
    print(f"申請金額:{money(q['from'], q['amount_src'])}")
    print(f"手續費(%):{money(q['from'], q['pct_fee_src'])}")
    print(f"手續費(固定):{money(q['from'], q['flat_fee_src'])}")
    print(f"手續費合計:{money(q['from'], q['fees_src_total'])}")
    print(f"扣除手續費後淨額:{money(q['from'], q['net_src_after_fees'])}")
    print(f"中間價({q['from']}→{q['to']}):{q['mid_rate_src_to_dst']:.6f} {q['to']}/{q['from']}")
    print(f"匯率價差(margin):{q['fx_margin']*100:.2f}%")
    print(f"實際成交匯率:{q['eff_rate_after_margin']:.6f} {q['to']}/{q['from']}")
    print(f"理想可得(無成本):{money(q['to'], q['ideal_dst_no_cost'])}")
    print(f"匯率價差損耗:約 {money(q['to'], q['fx_margin_loss_dst'])}")
    print(f"➡️ 實際入帳:{money(q['to'], q['receive_dst'])}")

# === 範例 1:用 TWD 付款給美國商家(TWD→USD)===
q1 = quote(amount_src=10000, src="TWD", dst="USD")
print_receipt(q1)

print("\n")

# === 範例 2:用 USD 付款給歐洲商家(USD→EUR)===
q2 = quote(amount_src=300, src="USD", dst="EUR")
print_receipt(q2)

你會在終端看到

  • 手續費(百分比+固定)、扣除後淨額
  • 中間價與實際成交匯率(含價差)
  • 理想可得(無成本) vs 實際入帳 的差距
    這樣你就能把「為什麼對方少收了錢」講清楚:不是商家耍賴,而是支付流程真的有成本。

延伸練習

  • 改數字玩出不同情境:把 FX_MARGIN 改成 0.3%、1.2% 比較差異。
  • 加上最小手續費門檻:例如金額太小,一律收 NT$30。
  • 輸出報表:把結果寫入 CSV,做多筆跨境付款的比較表。

上一篇
用 Python 做一個「迷你行動支付錢包」:儲值、付款連結、交易紀錄
下一篇
用 Python 做一個信用評分小工具
系列文
30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言